/**
 * BH1750光照强度传感器驱动
 * 使用I2C接口通信
 */

#include "bh1750.h"
#include "stdio.h"

// I2C超时定义
#define I2C_TIMEOUT 10000

// 延时函数
static void Delay_us(uint32_t us) {
    uint32_t count = us * 8; // 72MHz时钟
    while (count--) {
        __NOP();
    }
}

// 等待I2C事件
static uint8_t I2C_WaitEvent(I2C_TypeDef* I2Cx, uint32_t event) {
    uint32_t timeout = I2C_TIMEOUT;
    while (!I2C_CheckEvent(I2Cx, event)) {
        if (--timeout == 0) return 0;
    }
    return 1;
}

// BH1750初始化
void BH1750_Init(void) {
    // 上电
    BH1750_Power_On();
    
    // 延时等待稳定
    Delay_us(20000); // 20ms
    
    // 设置为连续高分辨率模式
    BH1750_Set_Mode(BH1750_CMD_CONT_H_MODE);
    
    // 延时等待第一次测量完成
    Delay_us(120000); // 120ms
    
    printf("BH1750光照传感器初始化完成\r\n");
}

// 设置测量模式
uint8_t BH1750_Set_Mode(uint8_t mode) {
    // 发送起始信号
    I2C_GenerateSTART(I2C1, ENABLE);
    if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)) return 0;
    
    // 发送设备地址
    I2C_Send7bitAddress(I2C1, BH1750_I2C_ADDR, I2C_Direction_Transmitter);
    if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) return 0;
    
    // 发送命令
    I2C_SendData(I2C1, mode);
    if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) return 0;
    
    // 发送停止信号
    I2C_GenerateSTOP(I2C1, ENABLE);
    
    return 1;
}

// 上电
uint8_t BH1750_Power_On(void) {
    return BH1750_Set_Mode(BH1750_CMD_POWER_ON);
}

// 断电
uint8_t BH1750_Power_Down(void) {
    return BH1750_Set_Mode(BH1750_CMD_POWER_DOWN);
}

// 复位
uint8_t BH1750_Reset(void) {
    return BH1750_Set_Mode(BH1750_CMD_RESET);
}

// 设置测量时间
uint8_t BH1750_Set_Measurement_Time(uint8_t time) {
    uint8_t high_time, low_time;
    
    // 计算高字节和低字节
    high_time = (0x40 | (time >> 5));
    low_time = (0x60 | (time & 0x1F));
    
    // 发送高字节
    I2C_GenerateSTART(I2C1, ENABLE);
    if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)) return 0;
    
    I2C_Send7bitAddress(I2C1, BH1750_I2C_ADDR, I2C_Direction_Transmitter);
    if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) return 0;
    
    I2C_SendData(I2C1, high_time);
    if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) return 0;
    
    I2C_GenerateSTOP(I2C1, ENABLE);
    
    // 延时
    Delay_us(1000);
    
    // 发送低字节
    I2C_GenerateSTART(I2C1, ENABLE);
    if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)) return 0;
    
    I2C_Send7bitAddress(I2C1, BH1750_I2C_ADDR, I2C_Direction_Transmitter);
    if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) return 0;
    
    I2C_SendData(I2C1, low_time);
    if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) return 0;
    
    I2C_GenerateSTOP(I2C1, ENABLE);
    
    return 1;
}

// 读取光照强度
uint16_t BH1750_Read_Lux(void) {
    uint8_t rx_data[2];
    uint16_t raw_data;
    float lux;
    
    // 根据当前模式等待测量完成
    Delay_us(120000); // 120ms (高分辨率模式)
    
    // 发送起始信号
    I2C_GenerateSTART(I2C1, ENABLE);
    if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)) return 0;
    
    // 发送设备地址 (读取模式)
    I2C_Send7bitAddress(I2C1, BH1750_I2C_ADDR, I2C_Direction_Receiver);
    if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)) return 0;
    
    // 读取高字节
    if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)) return 0;
    rx_data[0] = I2C_ReceiveData(I2C1);
    
    // 读取低字节 (不发送ACK)
    I2C_AcknowledgeConfig(I2C1, DISABLE);
    if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)) return 0;
    rx_data[1] = I2C_ReceiveData(I2C1);
    
    // 发送停止信号
    I2C_GenerateSTOP(I2C1, ENABLE);
    // 重新使能ACK
    I2C_AcknowledgeConfig(I2C1, ENABLE);
    
    // 组合数据
    raw_data = (rx_data[0] << 8) | rx_data[1];
    
    // 计算光照强度 (1.2 / 1.0 是测量时间系数)
    lux = (float)raw_data / 1.2;
    
    printf("光照强度: %.0f lux\r\n", lux);
    
    return (uint16_t)lux;
}

// 简化的读取函数 (适用于连续模式)
uint16_t BH1750_Read_Lux_Simple(void) {
    uint8_t rx_data[2];
    uint16_t raw_data;
    float lux;
    
    // 直接读取数据 (假设已经处于连续模式)
    I2C_GenerateSTART(I2C1, ENABLE);
    if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)) return 0;
    
    I2C_Send7bitAddress(I2C1, BH1750_I2C_ADDR, I2C_Direction_Receiver);
    if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)) return 0;
    
    // 读取高字节
    if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)) return 0;
    rx_data[0] = I2C_ReceiveData(I2C1);
    
    // 读取低字节
    I2C_AcknowledgeConfig(I2C1, DISABLE);
    if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)) return 0;
    rx_data[1] = I2C_ReceiveData(I2C1);
    
    I2C_GenerateSTOP(I2C1, ENABLE);
    I2C_AcknowledgeConfig(I2C1, ENABLE);
    
    // 计算光照强度
    raw_data = (rx_data[0] << 8) | rx_data[1];
    lux = (float)raw_data / 1.2;
    
    return (uint16_t)lux;
}
